from anim3d import *
import math

max_height = 10
class GameObject:
    def __init__(self, p = [0,0,0], v=[0,0,0], w = 10, h = 10, aobj = None):
        self.pos = p
        self.vel = v
        self.width = w
        self.height = h
        self.animobj = aobj
        self.auto_rotate = True #delete all objects on collision which do not auto_rotate 

    def setAnimObj(self, obj):
        self.animobj = obj

    def draw(self):
        if self.animobj == None:
            return
        glPushMatrix()
        glTranslatef(self.pos[0], self.pos[1], self.pos[2])
        if self.auto_rotate:
            if self.vel[0] > 0:
                glRotatef(45, 0, 0, 1)
            elif self.vel[0] < 0:
                glRotatef(-45, 0, 0, 1)
        self.animobj.renderObject()
        glPopMatrix()

    def jump(self):
        self.vel[2] = 0.5

    def setSpeed(self, v):
        self.vel[0] = 0
        self.vel[1] = v
        self.vel[2] = 0

    def setAnim(self, action):
        if self.animobj:
            self.animobj.setAction(action)

    def update(self):
        self.pos[0] += self.vel[0]
        self.pos[1] += self.vel[1]
        self.pos[2] += self.vel[2]
        #if the object was jumping, restrict at max height
        if self.pos[2] > max_height:
            self.vel[2] = -self.vel[2]
        #if the object was falling after a jump, vel < 0 so
        #stop it before it goes under ground
        if self.pos[2] < 0 and self.vel[2] < 0:
            self.vel[2] = 0
            self.pos[2] = 0
            if self.vel[0] or self.vel[1]:
                self.setAnim('run')
            else:
                self.setAnim('idle')

        #animation update
        if self.animobj == None:
            return
        self.animobj.cur_frame += 1        
        
    def sphereCollide(self, point, r2):
        """Returns 1 if colliding 0 if not colliding"""
    #do a sphere bounding collision
    #distance between two points should be > r1 + r2
        p = self.pos
        p1 = point
        r1 = self.width
        d2 = (p[0] - p1[0]) * (p[0]-p1[0]) + (p[1]-p1[1])*(p[1]-p1[1]) + (p[2]-p1[2])*(p[2]-p1[2])
        if d2 < (r1*r1 + r2*r2):
            return True
        return False

        
class NPC:
    bat_model = Model(data.filepath('bat.txt'))
    spike_model = Model(data.filepath('spikes.txt'))
    puzzle_model = Model(data.filepath('puzzlecube.txt'))
    def __init__(self, name = 'npc', p = [0,0,0], v=[0,0,0], w = 10, h = 10):

        self.obj = GameObject(p, v, 5, 5)#SimplePolygon() #GameObject(p, v, w, h)
        tmp = AnimObject()
        self.delete_on_collision = True
        if name == 'bat':
            tmp.setModel(NPC.bat_model)
            tmp.setAction('flapping')
            self.delete_on_collision = False
        elif name == 'spikes':
            tmp.setModel(NPC.spike_model)
            tmp.setAction('idle')
            self.delete_on_collision = False
        elif name == 'puzzle':
            tmp.setModel(NPC.puzzle_model)
            tmp.setAction('idle')
            tmp.w = 10
            tmp.h = 10

        self.obj.setAnimObj(tmp)
        self.obj.auto_rotate = False

        self.name = name
        self.p1 = ()
        self.p2 = ()

    def setPatrol(self, p1, p2):
        self.p1 = p1
        self.p2 = p2
        if self.name == 'puzzle':
            sv = [p1[0] + p2[0], p1[1] + p2[1], p1[2]+p2[2]]
            self.obj.pos = [sv[0]/2.0, sv[1]/2.0, sv[2]/2.0]
            return
        dv  = (p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2])
        d = math.sqrt(dv[0]*dv[0] + dv[1]*dv[1] + dv[2]*dv[2])
        if d > 1:
#            print dv
            speed = 0.3
            self.obj.vel = (dv[0]/d * speed, dv[1]/d * speed, dv[2]/d *speed)
#            print self.p1, self.p2, self.obj.vel

    def update(self):
        p1 = self.p1
        p2 = self.p2
        if self.obj.sphereCollide(self.p2, 1):
            self.setPatrol(p2, p1)
        self.obj.update()

    def draw(self):
        #self.obj.renderObject(self.p1, self.p2)
        #self.obj.renderObject()
        self.obj.draw()

    def sphereCollide(self, p, r):
        return self.obj.sphereCollide(p, r)
